package cate.game.pvp.eliterace.simulator;

import cate.common.table.d.GDFight;
import cate.game.pvp.eliterace.data.*;
import cate.game.pvp.eliterace.handler.*;
import cate.game.pvp.eliterace.timer.EliteRaceTimerTask.Settings;
import com.google.common.collect.Lists;

import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

import static cate.game.pvp.eliterace.util.EliteRaceSpecUtils.getFinalFlag;
import static cate.game.pvp.eliterace.util.EliteRaceSpecUtils.isMatchFinalSimulator;

public class BothEliteRaceFinalSimulator extends BaseEliteRaceBetSimulator {
    private final List<EliteRaceRecord> nextRecordList = Lists.newArrayList();

    public BothEliteRaceFinalSimulator(Supplier<EliteRaceKV> kvSupplier,
                                       Supplier<EliteRaceRecordOperation> recordOperationSupplier,
                                       Supplier<EliteRacePsOperation> psOperationSupplier,
                                       Supplier<EliteRaceFightOperation> fightOperationSupplier,
                                       Supplier<EliteRaceRankRwdOperation> rankRwdOperationSupplier,
                                       Supplier<EliteRaceBetOperation> betOperationSupplier,
                                       Supplier<EliteRaceVideoOperation> videoOperationSupplier) {
        super(
                kvSupplier,
                recordOperationSupplier,
                psOperationSupplier,
                fightOperationSupplier,
                rankRwdOperationSupplier,
                betOperationSupplier,
                videoOperationSupplier
        );
    }

    @Override
    protected int getPeriodFlag(Settings settings) {
        return getFinalFlag(settings);
    }

    @Override
    public boolean isMatch(Settings settings) {
        return isMatchFinalSimulator(settings);
    }

    @Override
    protected List<EliteRaceRecord> query(Settings settings) {
        EliteRaceRecordOperation recordOperation = getRecordOperation();
        EliteRaceSpec spec = settings.getSpec();
        EliteRaceSpec querySpec = EliteRaceSpec.ofFinal(spec.getSeason(), spec.getRound());
        List<EliteRaceRecord> queryList = recordOperation.query(querySpec);
        return Lists.newArrayList(queryList);
    }

    @Override
    public void afterRunWith() {
        EliteRaceRecordOperation recordOperation = getRecordOperation();
        nextRecordList.forEach(recordOperation::addRecord);
        nextRecordList.clear();
    }

    @Override
    public void afterHandleFightTask(EliteRaceRecord recordTask) {
        EliteRaceSpec spec = recordTask.getSpec();

        if (spec.getRound() < 2) {
            byte winner = recordTask.getWinner();
            EliteRaceSpec nSpec = EliteRaceSpec.of(
                    spec.getSeason(),
                    spec.getPeriod(),
                    spec.getGroup(),
                    (byte) (spec.getRound() + 1),
                    (byte) 0);
            byte nIndex = (byte) (recordTask.getIndex() / 2);
            EliteRaceRecord nRecord = nextRecordList.stream()
                    .filter(rd -> rd.getIndex() == nIndex && rd.getSpec().equals(nSpec))
                    .findAny()
                    .orElse(null);
            if (Objects.isNull(nRecord)) {
                nRecord = EliteRaceRecord.of(nSpec, null, null);
                nRecord.setIndex(nIndex);
                nextRecordList.add(nRecord);
            }
            String wUid = (winner == GDFight.Team.A)
                    ? recordTask.getIdA()
                    : recordTask.getIdB();

            if (recordTask.getIndex() % 2 == 0) {
                nRecord.setIdA(wUid);
            } else {
                nRecord.setIdB(wUid);
            }
        }
    }
}
